/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	CollectionMatcher.java
 * 模块说明：	
 * 修改历史：
 * Nov 1, 2007 - lxm - 创建。
 */
package com.hd123.rumba.util;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * 提供了不同质集合的比较运算。
 * <p>
 * 
 * 假设有两个元素类型不同的集合Collection。对象构造的时候，需要指定两个集合中不同类型的元素应如何判断两者匹配，调用者可以通过{@link ElementMatcher}
 * 进行客户化匹配运算。于此同时提供了默认实现，即元素的比较依据equals的返回结果。
 * <p>
 * 
 * 可以通过{@link #multiple(Collection, Collection)}取得交集，还可以通过{@link #subtractA(Collection, Collection)}和{@link #subtractB(Collection, Collection)}
 * 进行集合的减法运算。
 * <p>
 * 
 * @see ElementMatcher
 * @author lxm
 * 
 */
public class CollectionMatcher<A, B> {

  private ElementMatcher<A, B> em;

  /**
   * 构造函数。用此方法所构造的对象，采用默认的Object.equals方法进行比较。
   * 
   */
  public CollectionMatcher() {
    super();
    this.em = new ElementMatcher<A, B>();
  }

  /**
   * 构造函数。调用者可以通过此方法实现不同质集合的比较。
   * 
   * @param em
   *          指定的元素比较器对象。
   */
  public CollectionMatcher(ElementMatcher<A, B> em) {
    super();
    this.em = em;
  }

  /**
   * 求交集运算。即找到两个指定的集合中所有匹配的元素对。
   * 
   * @param colA
   *          指定的集合
   * @param colB
   *          指定的集合
   * @return 返回的运算结果是一个Map，其中的key中存放的是colA中的元素，value中存放的是colB中的元素。若没有匹配的
   *         则返回长度为0的Map。
   * @throws Exception
   */
  public Map<A, B> multiple(Collection<A> colA, Collection<B> colB) throws Exception {
    if (colA == null)
      throw new Exception("指定的参数colLeft不可为null。");
    if (colB == null)
      throw new Exception("指定的参数colRight不可为null。");
    Map<A, B> map = new HashMap<A, B>();
    for (A a : colA)
      for (B b : colB)
        if (em.match(a, b)) {
          map.put(a, b);
          break;
        }
    return map;
  }

  /**
   * 集合减法运算。即找到colA中所有没有与colB匹配成功的元素。
   * 
   * @param colA
   *          指定被减数集合。
   * @param colB
   *          指定减数集合。
   * @return 返回的结果是一个Collection，其中的元素为colA的元素。若没有符合条件的元素，则返回空集。
   * @throws Exception
   */
  public Collection<A> subtractA(Collection<A> colA, Collection<B> colB) throws Exception {
    if (colA == null)
      throw new Exception("指定的参数colLeft不可为null。");
    if (colB == null)
      throw new Exception("指定的参数colRight不可为null。");
    Collection<A> col = new HashSet<A>();
    for (A a : colA) {
      boolean matched = false;
      for (B b : colB)
        if (em.match(a, b)) {
          matched = true;
          break;
        }
      if (!matched)
        col.add(a);
    }
    return col;
  }

  /**
   * 集合减法运算。即找到colB中所有没有与colA匹配成功的元素。
   * 
   * @param colB
   *          指定被减数集合。
   * @param colA
   *          指定减数集合。
   * @return 返回的结果是一个Collection，其中的元素为colB的元素。若没有符合条件的元素，则返回空集。
   * @throws Exception
   */
  public Collection<B> subtractB(Collection<B> colB, Collection<A> colA) throws Exception {
    if (colA == null)
      throw new Exception("指定的参数colLeft不可为null。");
    if (colB == null)
      throw new Exception("指定的参数colRight不可为null。");
    Collection<B> col = new HashSet<B>();
    for (B b : colB) {
      boolean matched = false;
      for (A a : colA)
        if (em.match(a, b)) {
          matched = true;
          break;
        }
      if (!matched)
        col.add(b);
    }
    return col;
  }

}
